package com.api.test;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;

import com.zyncro.api.model.IApiType;

public final class AssertApi {

	private AssertApi() {
	}

	public static void assertUrnType(String actualUrn, UrnType urnTypeExpected) {

		if (actualUrn == null || urnTypeExpected == null) {

			throw new IllegalArgumentException("ActualUrn and UrnExpected cannot be null");
		}

		if (!actualUrn.matches(urnTypeExpected.getPattern())) {

			throw new AssertionError(String.format("Urn '%s' does not match urn %s pattern: '%s'", actualUrn, urnTypeExpected.name(),
					urnTypeExpected.getPattern()));
		}
	}

	public static void assertApiType(int actualValue, Enum<? extends IApiType> expected) {

		if (expected == null) {

			throw new IllegalArgumentException("ActualUrn and UrnExpected cannot be null");
		}

		Class<? extends Enum<? extends IApiType>> enumClass = expected.getDeclaringClass();
		Enum<? extends IApiType> actual = getApiTypeForValue(enumClass, actualValue);

		if (actual != expected) {

			IApiType expectedType = (IApiType) expected;

			throw new AssertionError(String.format("ApiType value '%s' does not match %s.%s value '%s'", actualValue, expected.getClass()
					.getSimpleName(), expected.name(), expectedType.getId()));
		}
	}

	private static Enum<? extends IApiType> getApiTypeForValue(Class<? extends Enum<? extends IApiType>> enumClass, int actualValue) {

		Enum<? extends IApiType> value = null;

		Enum<? extends IApiType>[] values = enumClass.getEnumConstants();

		int i = 0;

		while (i < values.length && value == null) {

			IApiType enumValue = (IApiType) values[i];

			if (enumValue.getId() == actualValue) {

				value = values[i];
			} else {
				i++;
			}
		}
		return value;
	}

	public static void assertEqualStreams(InputStream is1, InputStream is2) {

		boolean areEqual = false;

		try {
			areEqual = areInputStreamEquals(is1, is2);
		} catch (IOException ex) {

			throw new IllegalStateException("Couldn't assert input streams");
		}

		if (!areEqual) {

			throw new AssertionError("Input streams dont match");
		}
	}

	private static boolean areInputStreamEquals(InputStream is1, InputStream is2) throws IOException {

		BufferedInputStream input1 = new BufferedInputStream(is1);
		BufferedInputStream input2 = new BufferedInputStream(is2);

		int ch = input1.read();
		while (-1 != ch) {
			int ch2 = input2.read();
			if (ch != ch2) {
				return false;
			}
			ch = input1.read();
		}

		int ch2 = input2.read();
		return (ch2 == -1);
	}
}
